﻿/*
* Copyright (c) 2006-2007 Erin Catto http://www.gphysics.com
*
* This software is provided 'as-is', without any express or implied
* warranty.  In no event will the authors be held liable for any damages
* arising from the use of this software.
* Permission is granted to anyone to use this software for any purpose,
* including commercial applications, and to alter it and redistribute it
* freely, subject to the following restrictions:
* 1. The origin of this software must not be misrepresented; you must not
* claim that you wrote the original software. If you use this software
* in a product, an acknowledgment in the product documentation would be
* appreciated but is not required.
* 2. Altered source versions must be plainly marked as such, and must not be
* misrepresented as being the original software.
* 3. This notice may not be removed or altered from any source distribution.
*/


package TestBed{
	
	
	
	import Box2D.Collision.*;
	import Box2D.Collision.Shapes.*;
	import Box2D.Common.*;
	import Box2D.Common.Math.*;
	import Box2D.Dynamics.*;
	import Box2D.Dynamics.Contacts.*;
	import Box2D.Dynamics.Joints.*;
	
	import General.Input;
	
	import flash.display.Sprite;
	import flash.events.MouseEvent;
	
	
	
	public class TestTheoJansen extends Test{
		
		
		private var shapeType:int=0;
		private var downPoint:b2Vec2;
		private var preBody:b2Body;
		public function TestTheoJansen(){
			
			// Set Text field
			
			// scale walker by variable to easily change size
			tScale = m_physScale * 2;
			
			// Set position in world space
			m_offset.Set(120.0/m_physScale, 250/m_physScale);
			m_motorSpeed = -2.0;
			m_motorOn = true;
			var pivot:b2Vec2 = new b2Vec2(0.0, -24.0/tScale);
			
			var pd:b2PolygonShape;
			var cd:b2CircleShape;
			var fd:b2FixtureDef;
			var bd:b2BodyDef;
			var body:b2Body;
			
			
			/*
			for (var i:int = 0; i < 40; ++i)
			{
				cd = new b2CircleShape(7.5/tScale);
				
				bd = new b2BodyDef();
				bd.type = b2Body.b2_dynamicBody;
				// Position in world space
				bd.position.Set((Math.random() * 620 + 10)/m_physScale, 350/m_physScale);
				
				body = m_world.CreateBody(bd);
				body.CreateFixture2(cd, 1.0);
			}
			
			*/
			{
				pd = new b2PolygonShape();
				pd.SetAsBox(75 / tScale, 30 / tScale);
				fd = new b2FixtureDef();
				fd.shape = pd;
				fd.density = 1.0;
				fd.filter.groupIndex = -1;
			//	fd.filter.categoryBits = 0;
			//	fd.filter.maskBits = 0;
				bd = new b2BodyDef();
				bd.type = b2Body.b2_dynamicBody;
				//bd.position = pivot + m_offset;
				bd.position = b2Math.AddVV(pivot, m_offset);
				m_chassis = m_world.CreateBody(bd);
				m_chassis.CreateFixture(fd);
			}
			
			
			
			{
				cd = new b2CircleShape(48 / tScale);
				fd = new b2FixtureDef();
				fd.shape = cd;
				fd.density = 1.0;
				fd.filter.groupIndex = -1;
			//	fd.filter.categoryBits = 0;
			//	fd.filter.maskBits = 0;
				bd = new b2BodyDef();
				bd.type = b2Body.b2_dynamicBody;
				//bd.position = pivot + m_offset;
				bd.position = b2Math.AddVV(pivot, m_offset);
				m_wheel = m_world.CreateBody(bd);
				m_wheel.CreateFixture(fd);
			}
		
			{
				var jd:b2RevoluteJointDef = new b2RevoluteJointDef();
				var po:b2Vec2 = pivot.Copy();
				po.Add(m_offset);
				jd.Initialize(m_wheel, m_chassis, po);
				jd.collideConnected = false;
				jd.motorSpeed = m_motorSpeed;
				jd.maxMotorTorque = 400.0;
				jd.enableMotor = m_motorOn;
				m_motorJoint = m_world.CreateJoint(jd) as b2RevoluteJoint;
			}
			
			/*
			var wheelAnchor:b2Vec2;
			
			//wheelAnchor = pivot + b2Vec2(0.0f, -0.8);
			wheelAnchor = new b2Vec2(0.0, 24.0/tScale);
			wheelAnchor.Add(pivot);
			
			CreateLeg(-1.0, wheelAnchor);
			CreateLeg(1.0, wheelAnchor);
			
			m_wheel.SetPositionAndAngle(m_wheel.GetPosition(), 120.0 * Math.PI / 180.0);
			CreateLeg(-1.0, wheelAnchor);
			CreateLeg(1.0, wheelAnchor);
			
			m_wheel.SetPositionAndAngle(m_wheel.GetPosition(), -120.0 * Math.PI / 180.0);
			CreateLeg(-1.0, wheelAnchor);
			CreateLeg(1.0, wheelAnchor);
			*/
			var cP:Sprite = new Sprite();
			cP.name = "showCP";
			cP.graphics.beginFill(0x000000,0.5);
			cP.graphics.drawCircle(0,0,20);
			cP.graphics.endFill();
			cP.x = -100;
			cP.y = 0;
			var pp:Sprite = new Sprite();
			pp.name = "showPP";	
			pp.graphics.beginFill(0x000000,0.5);
			pp.graphics.drawRect(0,0,20,20);
			pp.graphics.endFill();
			pp.x = -100;
			pp.y = 100;
			var jp:Sprite = new Sprite();
			jp.name = "showGP";
			jp.graphics.lineStyle(3,0x000000,0.5);
			jp.graphics.beginFill(0xFFFFFF,0.5);
			jp.graphics.drawCircle(0,0,20);
			jp.graphics.endFill();
			jp.x = -100;
			jp.y = 200;
			this.m_sprite.addChild(cP);
			this.m_sprite.addChild(pp);
			this.m_sprite.addChild(jp);
			this.m_sprite.addEventListener(MouseEvent.CLICK,mouseClickHandler);
		}
		
		private function mouseClickHandler(event:MouseEvent):void{
			if(event.target.name == "showCP"){
				shapeType = 0;
			}else if(event.target.name == "showPP"){
				shapeType = 1;
			}else if(event.target.name == "showGP"){
				shapeType = 2;
			}
			trace("ok");
		}
		
		private function CreateLeg(s:Number, wheelAnchor:b2Vec2):void{
			
			var p1:b2Vec2 = new b2Vec2(162 * s/tScale, 183/tScale);
			var p2:b2Vec2 = new b2Vec2(216 * s/tScale, 36 /tScale);
			var p3:b2Vec2 = new b2Vec2(129 * s/tScale, 57 /tScale);
			var p4:b2Vec2 = new b2Vec2( 93 * s/tScale, -24  /tScale);
			var p5:b2Vec2 = new b2Vec2(180 * s/tScale, -45  /tScale);
			var p6:b2Vec2 = new b2Vec2( 75 * s/tScale, -111 /tScale);
			
			//b2PolygonDef sd1, sd2;
			var sd1:b2PolygonShape = new b2PolygonShape();
			var sd2:b2PolygonShape = new b2PolygonShape();
			var fd1:b2FixtureDef = new b2FixtureDef();
			var fd2:b2FixtureDef = new b2FixtureDef();
			fd1.shape = sd1;
			fd2.shape = sd2;
			fd1.filter.groupIndex = -1;
			fd2.filter.groupIndex = -1;
			fd1.density = 1.0;
			fd2.density = 1.0;
			
			if (s > 0.0)
			{
				sd1.SetAsArray([p3, p2, p1]);
				sd2.SetAsArray([
					b2Math.SubtractVV(p6, p4),
					b2Math.SubtractVV(p5, p4),
					new b2Vec2()
					]);
			}
			else
			{
				sd1.SetAsArray([p2, p3, p1]);
				sd2.SetAsArray([
					b2Math.SubtractVV(p5, p4),
					b2Math.SubtractVV(p6, p4),
					new b2Vec2()
					]);
			}
			
			//b2BodyDef bd1, bd2;
			var bd1:b2BodyDef = new b2BodyDef();
			bd1.type = b2Body.b2_dynamicBody;
			var bd2:b2BodyDef = new b2BodyDef();
			bd2.type = b2Body.b2_dynamicBody;
			bd1.position.SetV(m_offset);
			bd2.position = b2Math.AddVV(p4, m_offset);
			
			bd1.angularDamping = 10.0;
			bd2.angularDamping = 10.0;
			
			var body1:b2Body = m_world.CreateBody(bd1);
			var body2:b2Body = m_world.CreateBody(bd2);
			
			body1.CreateFixture(fd1);
			body2.CreateFixture(fd2);
			
			var djd:b2DistanceJointDef = new b2DistanceJointDef();
			
			// Using a soft distance constraint can reduce some jitter.
			// It also makes the structure seem a bit more fluid by
			// acting like a suspension system.
			djd.dampingRatio = 0.5;
			djd.frequencyHz = 10.0;
			
			djd.Initialize(body1, body2, b2Math.AddVV(p2, m_offset), b2Math.AddVV(p5, m_offset));
			m_world.CreateJoint(djd);
			
			djd.Initialize(body1, body2, b2Math.AddVV(p3, m_offset), b2Math.AddVV(p4, m_offset));
			m_world.CreateJoint(djd);
			
			djd.Initialize(body1, m_wheel, b2Math.AddVV(p3, m_offset), b2Math.AddVV(wheelAnchor, m_offset));
			m_world.CreateJoint(djd);
			
			djd.Initialize(body2, m_wheel, b2Math.AddVV(p6, m_offset), b2Math.AddVV(wheelAnchor, m_offset));
			m_world.CreateJoint(djd);
			
			var rjd:b2RevoluteJointDef = new b2RevoluteJointDef();
			
			rjd.Initialize(body2, m_chassis, b2Math.AddVV(p4, m_offset));
			m_world.CreateJoint(rjd);
			
		}
		
		
		
		public override function Update():void{
			
			var v:b2Vec2 = new b2Vec2;
			var isDown:Boolean = false;
			
			//case 'a':
			if (Input.isKeyPressed(65)){ // A
				m_chassis.SetAwake(true);
				var v:b2Vec2 = new b2Vec2();
				v.x = v.x -1;
				isDown = true;
				//m_motorJoint.SetMotorSpeed(-m_motorSpeed);
			}
			//case 's':
			if (Input.isKeyPressed(83)){ // S
				v.y = v.y + 1;
				isDown = true;
				m_chassis.SetAwake(true);
			//	m_motorJoint.SetMotorSpeed(0.0);
			}
			//case 'd':
			if (Input.isKeyPressed(68)){ // D
				v.x = v.x + 1;
				isDown = true;
				m_chassis.SetAwake(true);
			//	m_motorJoint.SetMotorSpeed(m_motorSpeed);
			}
			//case 'm':
			if (Input.isKeyPressed(87)){ // M
				v.y = v.y -1;
				isDown = true;
				m_chassis.SetAwake(true);
				
			//	m_motorJoint.EnableMotor(!m_motorJoint.IsMotorEnabled());
			}
			
			if (Input.isKeyPressed(72)){ // M
				//if(m_ball == null){
					var cd:b2CircleShape;
					var fd:b2FixtureDef;
					var bd:b2BodyDef;
					cd = new b2CircleShape(10 / tScale);
					fd = new b2FixtureDef();
					fd.shape = cd;
					fd.density = 1.0;
					fd.filter.groupIndex = -2;
					bd = new b2BodyDef();
					bd.type = b2Body.b2_dynamicBody;
					//bd.position = pivot + m_offset;
					bd.position.Set(m_wheel.GetPosition().x + Math.cos(m_wheel.GetAngle()) * 50 / tScale,m_wheel.GetPosition().y + Math.sin(m_wheel.GetAngle()) * 50 / tScale);
					m_ball = m_world.CreateBody(bd);			
					m_ball.CreateFixture(fd);
				//}
			}
			
			if (Input.isKeyPressed(74)){ // M
				//if(m_ball == null){
				var cd:b2CircleShape;
				var fd:b2FixtureDef;
				var bd:b2BodyDef;
				cd = new b2CircleShape(10 / tScale);
				fd = new b2FixtureDef();
				fd.shape = cd;
				fd.density = 1.0;
				fd.filter.groupIndex = -1;
				bd = new b2BodyDef();
				bd.type = b2Body.b2_dynamicBody;
				//bd.position = pivot + m_offset;
				var xA:Number = Math.cos(m_wheel.GetAngle()) * 50 / tScale;
				var yA:Number = Math.sin(m_wheel.GetAngle()) * 50/ tScale;
				bd.position.Set(m_wheel.GetPosition().x + xA,m_wheel.GetPosition().y + yA);
				m_ball = m_world.CreateBody(bd);
				var b2v:b2Vec2 = new b2Vec2();
				b2v.x = xA * 10;
				b2v.y = yA * 10;
				m_ball.SetLinearVelocity(b2v);
				m_ball.CreateFixture(fd);
				
				//}
			}
			if(isDown){
				m_chassis.SetLinearVelocity(v);
			}
			
			// Finally update super class
			super.Update();
		}
		
		
		public override function MouseDrag():void{
			// mouse press
			
			//trace(Input.mouseDown);
			if (Input.mouseDown && !m_mouseJoint){
				
				var body:b2Body = GetBodyAtMouse();
				
				if (body)
				{
					var md:b2MouseJointDef = new b2MouseJointDef();
					md.bodyA = m_world.GetGroundBody();
					md.bodyB = body;
					md.target.Set(mouseXWorldPhys, mouseYWorldPhys);
					md.collideConnected = true;
					md.maxForce = 300.0 * body.GetMass();
					m_mouseJoint = m_world.CreateJoint(md) as b2MouseJoint;
					body.SetAwake(true);
				}else{				
					if(Input.mousePressed){
						downPoint = new b2Vec2(mouseXWorldPhys,mouseYWorldPhys);
					}
				}
			}else if(Input.mouseReleased){
			//	if()
				
				
				var upPoint:b2Vec2 = new b2Vec2(mouseXWorldPhys,mouseYWorldPhys);
				if(upPoint.x < 0){
					trace("过线");
				}else{
					if(downPoint == null || downPoint.x<0){
						trace("过线");
					}else{
						if(shapeType == 0){
							var cd:b2CircleShape;
							var fd:b2FixtureDef;
							var bd:b2BodyDef;
							var b:b2Body;
							var r:Number = b2Math.Distance(downPoint,upPoint);
							cd = new b2CircleShape(r);
							fd = new b2FixtureDef();
							fd.shape = cd;
							fd.density = 1.0;
							fd.filter.groupIndex = -1;
							bd = new b2BodyDef();
							bd.type = b2Body.b2_dynamicBody;
							//bd.position = pivot + m_offset;
							bd.position = downPoint;
							b = m_world.CreateBody(bd);
							b.CreateFixture(fd);
						}else if(shapeType == 1){
							var pd:b2PolygonShape;
							var fd:b2FixtureDef;
							var bd:b2BodyDef;
							var b:b2Body;			
							var cV:b2Vec2 = b2Math.MulFV(0.5,b2Math.AddVV(downPoint,upPoint));
							var wV:b2Vec2 = b2Math.AbsV(b2Math.SubtractVV(downPoint,upPoint));
							fd = new b2FixtureDef();
							pd = new b2PolygonShape();
							pd.SetAsBox(wV.x/2, wV.y/2);
							fd.shape = pd;
							fd.density = 1.0;
							fd.filter.groupIndex = -1;
							bd = new b2BodyDef();
							bd.type = b2Body.b2_dynamicBody;
							//bd.position = pivot + m_offset;
							bd.position = cV;
							b = m_world.CreateBody(bd);
							b.CreateFixture(fd);					
						}else if(shapeType == 2){
							if(preBody == null){
								preBody = GetBodyAtMouse();
							}
							else{
//								var jd:b2RevoluteJointDef = new b2RevoluteJointDef();
//								var po:b2Vec2 = pivot.Copy();
//								po.Add(m_offset);
//								jd.Initialize(m_wheel, m_chassis, po);
//								jd.collideConnected = false;
//								jd.motorSpeed = m_motorSpeed;
//								jd.maxMotorTorque = 400.0;
//								jd.enableMotor = m_motorOn;
//								m_motorJoint = m_world.CreateJoint(jd) as b2RevoluteJoint;
//								
//								preBody = null;
							}
						}
					}
				}					
			}else{
				downPoint = null;
			}	
			
			// mouse release
			if (!Input.mouseDown){
				if (m_mouseJoint)
				{
					m_world.DestroyJoint(m_mouseJoint);
					m_mouseJoint = null;
				}
			}
			
			
			// mouse move
			if (m_mouseJoint)
			{
				var p2:b2Vec2 = new b2Vec2(mouseXWorldPhys, mouseYWorldPhys);
				m_mouseJoint.SetTarget(p2);
			}
		}
		
		
		//======================
		// Member Data 
		//======================
		private var tScale:Number;
		
		private var m_offset:b2Vec2 = new b2Vec2();
		private var m_chassis:b2Body;
		private var m_wheel:b2Body;
		private var m_motorJoint:b2RevoluteJoint;
		private var m_motorOn:Boolean = true;
		private var m_motorSpeed:Number;
		private var m_ball:b2Body;
		
	}
	
}